
if(!window.Berta) window.Berta = {};

Berta.EditorManager = new Class(function(){
    return {

		statics: {
    		_instance: null, // Singleton instance
    		instance: function(options) {
    			if(!Berta.EditorManager._instance) {
    				Berta.EditorManager._instance = new Berta.EditorManager(options);
    			}
    			
    			return Berta.EditorManager._instance;
    		},
    		
			plugins: {},
			addPlugin: function(pluginName, pluginClass) {
				if(jQuery.isArray(pluginName)) {
					for(var i = 0; i < pluginName.length; i++)
						this.plugins[pluginName[i]] = pluginClass;
				} else {
					this.plugins[pluginName] = pluginClass;
				}
			},
			
			defaultContext: Berta.Editor.PAGE_CONTEXT
		},
		
		defaults: {},
		options: {},
    	instances: [],	// Instances of editors
		
    	
		constructor: function(options) {
			this.options = $.extend(true, {}, this.defaults, options);
		},
    	
		
		//   .______    __    __  .______    __       __    ______    ////////////////////////////////////////////////////////////
		//   |   _  \  |  |  |  | |   _  \  |  |     |  |  /      |   ////////////////////////////////////////////////////////////
		//   |  |_)  | |  |  |  | |  |_)  | |  |     |  | |  ,----'   ////////////////////////////////////////////////////////////
		//   |   ___/  |  |  |  | |   _  <  |  |     |  | |  |        ////////////////////////////////////////////////////////////
		//   |  |      |  `--'  | |  |_)  | |  `----.|  | |  `----.   ////////////////////////////////////////////////////////////
		//   | _|       \______/  |______/  |_______||__|  \______|   ////////////////////////////////////////////////////////////

		
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		//  A P I   ////////////////////////////////////////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////	
		
		/**
		 * Create editor for a DOM element and add it to the instances list
		 * @param {DOMElement} element		DOM element to make editable
		 * @param {String} variable			REST path (e.g. /site/heading)
		 * @param {String} pluginName		Name of the plugin (default = 'TextLine')
		 * @param {Object} pluginOptions	Plugin specific options. see each plugin for reference
		 * @param {String} context			(optional) Context in which to put the editor in
		 * @return {Berta.Editor} 			Instance of the editor, or null in case of an error
		 */
		create: function(element, type, options, pluginOptions) {
			
			var o = jQuery.extend({}, options, {
				
				// Append element
				'element': element,
				
				// Add internal save handlers to options
				'save': this._(save),
				'saveStop': this._(saveStop),
				
				// Append type and pluginOptions to main options
				'type': type,
				'pluginOptions': pluginOptions
			});

			//console.log('editormanager create ', element, o);

			if (Berta.EditorManager.plugins[type]) {
				var instance = new Berta.EditorManager.plugins[type](o);
				instance.on();
				
				return this.addInstance(instance);
			} else {
				$.log('Berta.EditorManager: Plugin "' + type + '" not defined! element:', element);
				return null; // plugin does not exist
			}
		},
		
		/**
		 * Destroys editor for element
		 * @param {DOMElement} 			DOM element for which to destroy the editor
		 * @param {Object} doSave		Save editor (if in editing mode) before destroying
		 */
		destroy: function(element, doSave) {
			var ed = this.getInstanceByElement(element);
			//console.log('editormanager off', element, ed);
			if(ed) {
				ed.destroy(doSave);
				this.removeInstance(ed);
				return true;
			}
			return false;
		},
		
		/**
		 * Stops editing in all editors where editing is going on
		 * @param {Boolean} doSave		Whether to save after stop editing (default = false)
		 * @param {String} context		Conext for which to stop editing
		 * @param {Function} callback	Function to execute after stopping
		 */
		stopEditingAll: function(doSave, context, callback) {
			if(!context) context = this.statics.defaultContext;
			 // ... TODO
		},
		
		/**
		 * Desotrys all editors
		 * @param {Boolean} doSave		Whether to save before destroying (default = false)
		 * @param {String} context		Context for which to remove editors
		 * @param {Function} callback	Function to execute after destroying
		 */
		destroyAll: function(doSave, context, /* TODO: */ callback) {
			//if(!context) context = this.statics.defaultContext;
			
			for(i = 0; i < this.instances.length; i++) {
				if(!context || this.instances[i].options.context == context) {
					this.instances[i].destroy(doSave);
				}
			}
			this.instances = [];
		},
	
	
	
		registerEditables: function(elementOrXPath, context, onChange, onSave, onRevert) {
			var o = {
				context: context,
				callbacks: { }
			};
			if(onChange) o.callbacks.onChange = onChange;
			if(onSave) o.callbacks.onSave = onSave;
			if(onRevert) o.callbacks.onRevert = onRevert;
			
			$(elementOrXPath).bertaEditableOn(o);
 		},
		unregisterEditables: function(elementOrXPath) {
			$(elementOrXPath).bertaEditableOff();
 		},
	
	
	
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		//  INSTANCES HASH MANAGEMENT   ////////////////////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	
		addInstance: function(editorInstance) {
			//$.log('EditorManager: addInstance', editorInstance);
			this.instances.push(editorInstance);
			return editorInstance;
		},
		removeInstance: function(editorInstance){
			//editorInstance.hide();
			//editorInstance.remove();
			var idx = -1;
			var idx = this.instances.indexOf(editorInstance);
			if (idx >= 0) {
				return this.instances.splice(idx, 1)[0];
			} else {
				return false;
			}
		},
		getInstanceByElement: function(element) {
			for(i = 0; i < this.instances.length; i++) {
				if(this.instances[i].element.get(0) == element.get(0)) {
					return this.instances[i];
				}
			}
			
			return false;
		}
		
    };
	
	
	
	
	
	//   .______   .______     __  ____    ____  ___   .___________. _______    //////////////////////////////////////////////////
	//   |   _  \  |   _  \   |  | \   \  /   / /   \  |           ||   ____|   //////////////////////////////////////////////////
	//   |  |_)  | |  |_)  |  |  |  \   \/   / /  ^  \ `---|  |----`|  |__      //////////////////////////////////////////////////
	//   |   ___/  |      /   |  |   \      / /  /_\  \    |  |     |   __|     //////////////////////////////////////////////////
	//   |  |      |  |\  \--.|  |    \    / /  _____  \   |  |     |  |____    //////////////////////////////////////////////////
	//   | _|      | _| `.___||__|     \__/ /__/     \__\  |__|     |_______|   //////////////////////////////////////////////////

	/**
	 * Saves data to rest variable
	 * @param	{String} route				Route name
	 * @param	{Object} route_replacements	Replacements for route URL, e.g., { id: 8 }		
	 * @param	{String} variable			Variable to save
	 * @param	{Mixed} value				Value to save for the variable
	 * @param	{Function} callback			callback to execute on save complete
	 * @return	{Berta.Server.Process}		Server process
	 */
    function save(route_name, route_replacements, variable, value, params, callback) {
		
		var data = {};

	    if(jQuery.isArray(variable)) {
		    for(var v_part in variable) {
			    if(variable.hasOwnProperty(v_part)) {
				    data[variable[v_part]] = value[v_part];
			    }
		    }
	    } else {
			data[variable] = value;
	    }

		if(null !== params && typeof params === 'object') {
			jQuery.extend(data, params);
		}
		
		return Berta.Server.instance().put(
					Berta.Route.get(
						route_name, 
						route_replacements, 
						data
					), 
					this._(saveComplete, callback) 
					/* TODO: do we need error callback here? */
				);
    }
	function saveStop(id) {
		Berta.Server.instance().cancel(id);
	}
	function saveComplete(callback, xhrId, response) {
		if(jQuery.isFunction(callback)) {
			callback(response);
		}
	}
    
    
	
}());








